//-----------------------------------------------------------------------------------------------
// Author: Andre Van Der Merwe <dart@pobox.com>
// Project: .net Compound File (http://dotnetpcf.sourceforge.net)
// 
// Copyright (c) Andre Van Der Merwe 2000-2001
// Licence: BSD - see the licence.txt file or visit the project homepage
//-----------------------------------------------------------------------------------------------


//TODO change CFNames to inherit from StringCollection not Hashtable

namespace dotnetpcf.CompoundFile
{
   using System;
   using System.Diagnostics;
   using System.Collections;
   using System.Data;
   using System.IO;

   /// <summary>
   /// CFNames stores a list of all the "names" used by the compound file. These are strings such as the names of
   /// directories and files. Each of these items stored an ID of its name, rather than the string itself.
   /// </summary>
   internal class CFNames : Hashtable
   {
      public CFNames(  CompoundFileSys cf  ) : base()
      {
         m_cfParent = cf;
         m_Header.m_iMagic = SysInfo.MAGIC_NAMES_HEADER;
      }

      private BlockHeader m_Header = new BlockHeader();
      private CompoundFileSys m_cfParent;

      public void SaveToStream(  Stream strm  )
      {
         Debug.Assert(  null != strm  );
         if(  null == strm  )
            throw(  new CompoundFileException(  CompoundFileResult.cfrStreamIsNull  )  );

         m_Header.m_iTotalItems = (uint)Count;
         m_Header.SaveToStream(  strm  );

         BinaryWriter wrtr = new BinaryWriter(  strm  );
         IDictionaryEnumerator elems = GetEnumerator();

         while(  elems.MoveNext()  )
         {
            Debug.Assert(  elems.Value is string,  "invalid entry in the CFNames hashtable"  );

            wrtr.Write(  (uint)elems.Key  );
            wrtr.Write(  (string)elems.Value  );
         }
         
      }

      public void LoadFromStream(  Stream strm  )
      {
         Debug.Assert(  null != strm  );
         if(  null == strm  )
            throw(  new CompoundFileException(  CompoundFileResult.cfrStreamIsNull  )  );

         m_Header.LoadFromStream(  strm  );

         Debug.Assert(  SysInfo.MAGIC_NAMES_HEADER == m_Header.m_iMagic,  "Names magic number is invalid"  );
         if(  SysInfo.MAGIC_NAMES_HEADER != m_Header.m_iMagic  )
            throw(  new CompoundFileException(  CompoundFileResult.cfrInvalidNamesMagicNumbers  )  );

         BinaryReader rdr = new BinaryReader(  strm  );

         for(  uint i =0;  i < m_Header.m_iTotalItems;  ++i  )
            this[ rdr.ReadUInt32() ] = rdr.ReadString();
      }

      internal uint GetNextFreeNameID()
      {
            //Find a new ID
         uint iFirstFreeName = 0;
         while(  ContainsKey(  ++iFirstFreeName  )   )
         {}

         return iFirstFreeName;
      }

      public string GetNameByID(  uint iID  )
      {
         return (string)this[ iID ];
      }

      public void SetName(  uint iID,  string sStr  )
      {
         this[ iID ] = sStr;
      }

      public void RemoveName(  uint iID  )
      {
         Remove(  iID  );
      }
  }
}